import java.beans.*;


import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import java.util.Map.Entry;
import java.lang.Math;

import norsys.netica.*;
import norsys.neticaEx.NodeListEx;
import norsys.neticaEx.aliases.Node;


import java.net.URI;



public class NoisyHybridBean {

  private static int NUM_STATES = 2;

  public HashMap <String, Node> nodes;
  public HashMap <String, Node> nodes2;

  private NodeList nodeList;
  private NodeList parentListofNodeToConvert;
 
  private HashMap<String, Integer> parentIndices;
  
  public static Environ env;
  private String assocFileName;
  private String outputFileName;
  //private Net tempNet;
  private String logBuf = "";
  private String date;
  private Net tempNet;
  private NodeList nList;
  
  private association myAssociations;
  private int totalSNPs;
  private int totalTraits;
  
  private LinkedList<snp> snpListByRSquare;
  private LinkedList<String> traitList;
  private HashMap<String, snp> snpsInNet;
  private HashMap<String, Float> traitPrevalance;
  private LinkedList<partialAssociationElement> triangulations;
  private boolean printDebug = false;
	
  
  public NoisyHybridBean () {
    SimpleDateFormat sdf = new SimpleDateFormat( "MMM d, yyyy" );
    this.date = sdf.format( (new GregorianCalendar()).getTime() );
    nodes = new HashMap<String, Node>();
    nodes2 = new HashMap<String, Node>();
    myAssociations = new association();
    myAssociations.setPrintDebug(printDebug);
    snpListByRSquare = new LinkedList<snp> ();
    snpsInNet = new HashMap<String, snp> ();
    traitPrevalance = new HashMap<String, Float> ();
    totalSNPs = 0;
    totalTraits = 0;
  }

  
  
  public String initSession (){
 	String returnMsg = null;
    try {
    	env = new Environ ("Netica license code");
    
    	parentIndices = new HashMap<String, Integer>();
    	tempNet = new Net();
    	tempNet.setName("Hybrid");
      	
    	
    	
    }
    catch (Exception e) {
	returnMsg = e.getMessage();
	e.printStackTrace();
    }
    return returnMsg;
  }

  private void initTraitPrevalance(String filename)
  {
	  BufferedReader input;
	  try {
		  	input = new BufferedReader(new FileReader(filename));
	  	
		  try{
		
			if(traitPrevalance != null)
			{
				String line = null;
				while( (line = input.readLine()) != null)
				{
					String[] elements = line.split("\t");
				    traitPrevalance.put(elements[0], new Float(elements[1]));
				}
			}
			
		  } catch (IOException e) {
			  e.printStackTrace();
		  }
		} catch (FileNotFoundException e1) {
	 		e1.printStackTrace();
	  	}
  }
  private Net loadNet(Net net, HashMap <String, Node> nodes) throws Exception
  {
      if(net.getName() != null)
     {
       NodeList nodeList = net.getNodes();
 		
 		Iterator i = nodeList.iterator();
 		while(i.hasNext())
 		{
 			Node n = (Node)i.next();
 			nodes.put(n.getName(), n);
 		}
 		
 		net.compile();
 		return net;
     }
     else
     	return null;
  }
  
  /** 
   *  Removes the single link from node 'parent' to node 'child'.
   *  If there is no link from 'parent' to 'child', or more than one, it generates an error.
   *  @param parent the parent node
   *  @param child  the child node
   */
  static void delLink (Node parent, Node child) throws NeticaException {
      NodeList parents = child.getParents();
      int index = parents.indexOf (parent);
      child.deleteLink (index);
  }
  
  public void processRequest (String filename_org, String filename_other, String filename_trait_prevalance, Double threshold) {
      
  

      logBuf = ""; //resets log
  
      assocFileName = filename_org;
      outputFileName = filename_other;
      initTraitPrevalance(filename_trait_prevalance);
      partialAssociationElement.setThreshold(threshold);
      
      try{    
          //-- Do Netica stuff
          try {
    	  if (env == null) {
    	      env = Environ.getDefaultEnviron();
    	      if (env == null) {
    		  String errMsg = initSession();
    		  if (env == null) {
    		      System.out.println( errMsg );
    		      return; //no point in continuing
    		  }
    	      }
    	  }
      } catch (Exception e) {
	  //-- We log any exceptions.
	  //-- Suggestion: during development, you may want to have your jsp page display the
	  //-- exception stack trace by calling getLog() below.
    	  System.out.println( e.getMessage() );
      }


  	  
      
      totalSNPs = 0;
      totalTraits = 0;
      parseAssocFile(assocFileName);
      if(printDebug)
      {
      System.out.println("/************************************************************/");
      System.out.println("Total Duplicate Associations Found for input: " + myAssociations.getDuplicateAssociation());
      System.out.println("Total Associations Found: " + myAssociations.getTotalAssociation());
      Iterator<Map.Entry<String, associationElement>> assocIterator = myAssociations.getIterator();
      while(assocIterator.hasNext())
	   {
    	  System.out.println(assocIterator.next().getKey());
	   }
      System.out.println("/************************************************************/");
      }
      
      drawDAG();
      System.out.println("Writing to File Total SNPs: " + totalSNPs);
      
      String  fn = outputFileName.substring(0, outputFileName.indexOf("."));
      Streamer os1 = new Streamer(fn + "_SNP.dne" );
	    tempNet.write(os1);
		
      triangulate();
    	
      prune();
      
      System.out.println("Writing to File Pruned SNPs Network: ");
      
      Streamer os2 = new Streamer(fn + "_PrunedSNP.dne" );
	    tempNet.write(os2);
	
	    Iterator<snp> snpListIterator= snpListByRSquare.iterator();
	    if(printDebug)
      {
         while(snpListIterator.hasNext())
	       {
    	     System.out.println(snpListIterator.next().getName());
	       }
         System.out.println("/************************************************************/");
      }
      
      drawDAG_traits();
      System.out.println("Total Traits: " + totalTraits);
	  Iterator<String> traitListIterator= traitList.iterator();
	  if(printDebug)
      {
	  while(traitListIterator.hasNext())
	   {
    	  System.out.println(traitListIterator.next());
	   }
      System.out.println("/************************************************************/");
      }
	  removeCyclesBeforeCPT();
      computeCPT();
      
      computeCPTofTraits();
      
  
      boolean compiled = false;
     while(!compiled) 
     {
    	 try{
     
    	  tempNet.compile();
    	  compiled = true;
	      } catch(NeticaException e)
	      {
	    	  if(e.getMessage().contains("is a cycle (containing link"))
	    	  {
	    		  String [] msg = e.getMessage().split("->");
	    		  String [] n = msg[0].split("link");
	    		  String [] msgg = msg[1].split("\n");
	    		  String c_name = msgg[0].trim();
	    		  String n2 = c_name.substring(0,c_name.length()-1);
 
	    		  Node child = (Node) tempNet.getNode(n2);
	    		  Node parent = (Node) tempNet.getNode(n[1].trim());
 
	    		  removeCycles(parent, child);
	    	  }
	    	  else if(e.getMessage().contains("doesn't have a CPT table"))
	    	  {
 
	    		  String [] msg = e.getMessage().split("node");
	    		  String [] n = msg[0].split("rs");
	    		  String [] msgg = msg[1].split("\n");
	    		  String c_name = msgg[0].substring(2,msgg[0].indexOf("doesn't")-2);
	    		  
	    		  Node Odd_n = (Node) tempNet.getNode(c_name);
	    		  int size = Odd_n.getParents().size();
	    		  float[] cptRow = new float [size*2*2];
	    		  for(int i=0; i<cptRow.length; i++)
	    		  {
	    			  cptRow[i] = 0.5f;
	    		  }
	    		  Odd_n.setCPTable(cptRow);
	    		  
	    		  
	    	  }
	    	  else
	    	  {
	    		  System.out.println(e.getMessage());
	    	  }
	    		  
	      }
     }
     
      double size = tempNet.sizeCompiled();  
      System.out.println("Total compiled size: " + Double.toString(size));
      double memSize = tempNet.getEnviron().getMemoryUsageLimit(); 
      System.out.println("Total memory size: " + Double.toString(memSize));
      
      Streamer os = new Streamer(outputFileName);
	  tempNet.write(os);
	  
		
	  Net netToAbsorb = new Net(new Streamer (outputFileName));
	  
		//Absorb nodes
		 NodeList nodes = new NodeList (netToAbsorb);
		 Iterator<snp> snpNodeListIterator= snpListByRSquare.iterator();
	     while(snpNodeListIterator.hasNext())
		   {
	    	  snp thisSNP = snpNodeListIterator.next();
	    	  String name = thisSNP.getName();
	    	  
	    	  nodes.add(netToAbsorb.getNode(name));
	    	  
	    
		   } 
	     netToAbsorb.absorbNodes (nodes);
		
		Streamer os_mod = new Streamer(fn + "_absorbed.dne");
		netToAbsorb.write(os_mod);
		netToAbsorb.finalize();
		
		tempNet.finalize();
		tempNet = null;
      
	  
     } catch (Exception e) {
    	  //-- We log any exceptions.
    	  //-- Suggestion: during development, you may want to have your jsp page display the
    	  //-- exception stack trace by calling getLog() below.
    	 System.out.println( e.getMessage() );
     }
   System.out.println("SUCCESS!!!!!!");
  }
  
  private Float getPriorOdds(String trait)
  {
	  Float p = traitPrevalance.get(trait);
	  return (p / (1-p));
  }

  private void computeCPTofTraits()
  {
	  Iterator<String> traitListIterator= traitList.iterator();
	 	  
      while(traitListIterator.hasNext())
	   {
    	  String thisTrait = traitListIterator.next();
    	  Node n = null;
    	  int[]   pStates = null;
  	      double d = 0;  
  	      float [] cptRow = {0.5f, 0.5f};
		  String name = "", equation = "", params ="";	
		  if(printDebug)
		  {
			  System.out.println(thisTrait); 
		  }
		 try {
			 
			 n = (Node) tempNet.getNode(thisTrait);
			 if(n != null)
			 {
				NodeList children = n.getChildren();
				NodeList parents = n.getParents();
				
				if(parents.isEmpty()) // top node, then RA && NA = Marginals
				{
					pStates = new int[2];
					pStates[0] = 0;
					pStates[1] = 1;
					
				   if(cptRow[0] + cptRow[1] == 1.0)	
				   {
					   if(cptRow[0] > 1.0)
						{
							cptRow[0] = 1.0f;
							cptRow[1] = 0.0f;
							
						}
					   else if(cptRow[1] > 1.0)
						{
							cptRow[1] = 1.0f;
							cptRow[0] = 0.0f;
							
						}
					   n.setCPTable(pStates,cptRow);
				   }
				}
				else // there is a parent
				{
					Float priorOdds = getPriorOdds(thisTrait);
					
					equation = "P(" + thisTrait + " | ";
							
					for(int i=0; i <  parents.size(); i++)
					{
						float linkProbability = 0.0f;
						Node p = (Node) parents.getNode(i);
						name = p.getName();
						snp s = snpsInNet.get(name);
						if(s != null)
						{	
							Float lr = s.getSnpTraitLR(thisTrait);
							Float posteriorOdds = lr * priorOdds;
							linkProbability = posteriorOdds / (1 + posteriorOdds);
							if(i==0)
							{
								equation += name ;
							}
							else
							{
								equation += "," + name ;
							}
							if(i==0)
							{
								params += name + "," + linkProbability + "\n";
							}
							else
							{
								params += "," + name + "," + linkProbability + "\n";
							}
						}
					}
					equation += ") = NoisyOrDist(" + thisTrait + ", 0.0,\n" + params + ")\n";
					n.setEquation(equation);
					n.equationToTable(1,false, false);
							
				}
				 
			 }
			 
		  } 
		  catch (NeticaException e) 
		  {
			// TODO Auto-generated catch block
			e.printStackTrace();
		  }
	   	 
	   }
       
  }
  
  private NodeList findCommonChildren(Node n1, Node n2)
  {
	  NodeList n2ChildrenList = null;
	  NodeList n1ChildrenList = null;
	  HashMap<String, Node> n1ChildrenMap = new HashMap<String, Node>();
	  
	  try {
		  NodeList retVal = new NodeList(tempNet);
	  
		  n1ChildrenList = n1.getChildren();
		  n2ChildrenList = n2.getChildren();
	      Node n = null;
		  for(int i=0; i< n1ChildrenList.size(); i++)
		  {
			  n =  (Node) n1ChildrenList.getNode(i);  
			  n1ChildrenMap.put(n.getName(), n);
		  }
		  
		  for(int i=0; i< n2ChildrenList.size(); i++)
		  {
			  n =  (Node) n2ChildrenList.getNode(i);
			  if(n1ChildrenMap.get(n.getName()) != null)
			  {
				 retVal.add(n); 
			  }
			  
		  }
		  return retVal;
	  } catch (NeticaException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	  }
	  return null;
	  
	  
	  	
  }
  
  private void computeCPT()
  {
	  Iterator<snp> snpListIterator= snpListByRSquare.iterator();
      while(snpListIterator.hasNext())
	   {
    	  snp thisSNP = snpListIterator.next();
    	  String name = thisSNP.getName();
    	  Node n = null;
    	  int[]   pStates = null;
  	       float rSquare = 0, s1_ra,s1_na, s2_ra, s2_na;
  	      double d = 0;  
  	      float [] cptRow = {0.5f, 0.5f};
			  	   
		 try {
			 
			 n = (Node) tempNet.getNode(name);
			 if(n != null)
			 {
				NodeList children = n.getChildren();
				NodeList parents = n.getParents();
				
				if(parents.isEmpty()) // top node, then RA && NA = Marginals
				{
					pStates = new int[2];
					pStates[0] = 0;
					pStates[1] = 1;
					
				    cptRow[0] = thisSNP.getRaf(); 
					cptRow[1] = 1 - thisSNP.getRaf(); 
	
					if(cptRow[0] == 0.0 || cptRow[1] == 0.0)
					{
						continue;
					}
					if(cptRow[0] + cptRow[1] == 1.0)	
					{
						if(cptRow[0] > 1.0)
						{
							cptRow[0] = 1.0f;
							cptRow[1] = 0.0f;
							
						}
						else if(cptRow[1] > 1.0)
						{
							cptRow[1] = 1.0f;
							cptRow[0] = 0.0f;
							
						}
						n.setCPTable(pStates,cptRow);
					}
				}
				else // there is a parent
				{
					if(parents.size() == 1)
					{
					for(int i=0; i <  parents.size(); i++)
					{
						Node p = (Node) parents.getNode(i);
						associationElement ae = myAssociations.getAssociation(name + "-" + p.getName());
						if(ae == null)
						{
							// Try other key
							ae = myAssociations.getAssociation(p.getName()+ "-" + name);
						}
						if(ae != null)
						{	
							snp g_snp = ae.getGsnp();
							snp p_snp = ae.getPsnp();
							
							s1_ra = g_snp.getRaf();
							s1_na = 1-s1_ra;
							
							s2_ra = p_snp.getRaf();
							s2_na = 1-s2_ra;
							
							if(s1_ra == 0.0 || s2_ra == 0)
							{
								continue;
							}
							double val = s1_ra*s1_na*s2_ra*s2_na;
							d = java.lang.Math.sqrt(val) * java.lang.Math.sqrt(ae.getRsquared());
						
							
							float x = (s1_ra*s2_ra) + (float)d ;
							float y = (s1_ra*s2_na) - (float)d ;
							
							cptRow[0] = x / s1_ra;
							cptRow[1] = y / s1_ra;
							
							
								if(cptRow[0] > 1.0)
								{
									cptRow[0] = 1.0f;
									cptRow[1] = 0.0f;
									
								}
								else if(cptRow[1] > 1.0)
								{
									cptRow[1] = 1.0f;
									cptRow[0] = 0.0f;
									
								}
								n.setCPTable("true",cptRow);   // Risk Allele
	 
							float v = (s1_na*s2_ra) - (float)d;
							float w = (s1_na*s2_na) + (float)d;
							
							cptRow[0] = v / s1_na;
							cptRow[1] = w / s1_na;
							
	 
	 
								if(cptRow[0] > 1.0)
								{
									cptRow[0] = 1.0f;
									cptRow[1] = 0.0f;
									
								}
								else if(cptRow[1] > 1.0)
								{
									cptRow[1] = 1.0f;
									cptRow[0] = 0.0f;
									
								}
								n.setCPTable("false",cptRow);  // Normal Allele
	 
							
							
							
						}
					}
						if(printDebug)
						{
							System.out.println(name);
						}
					} // parent size == 1
					else
					{
						System.out.println("computeCPT(): parent size > 1 for " + name);
						float linkProbability = 0.0f;
						String equation = "", params = "";
						equation = "P(" + name + " | ";
				
						for(int i=0; i <  parents.size(); i++)
						{
							Node p = (Node) parents.getNode(i);
							associationElement ae = myAssociations.getAssociation(name + "-" + p.getName());
							if(ae == null)
							{
								// Try other key
								ae = myAssociations.getAssociation(p.getName()+ "-" + name);
							}
							if(ae != null)
							{	
								snp g_snp = ae.getGsnp();
								snp p_snp = ae.getPsnp();
								
								s1_ra = g_snp.getRaf();
								s1_na = 1-s1_ra;
								
								s2_ra = p_snp.getRaf();
								s2_na = 1-s2_ra;
								
								if(s1_ra == 0.0 || s2_ra == 0)
								{
									continue;
								}
								double val = s1_ra*s1_na*s2_ra*s2_na;
								d = java.lang.Math.sqrt(val) * java.lang.Math.sqrt(ae.getRsquared());
							
								
								float x = (s1_ra*s2_ra) + (float)d ;
								float y = (s2_ra*s1_na) - (float)d ;
								
								linkProbability = x / s2_ra;
								if(linkProbability > 1.0)
								{
									linkProbability = 0.99f;
								}
								if(i==0)
								{
									equation += p.getName() ;
								}
								else
								{
									equation += "," + p.getName() ;
								}
								if(i==0)
								{
									params += p.getName() + "," + linkProbability + "\n";
								}
								else
								{
									params += "," + p.getName() + "," + linkProbability + "\n";
								}		
											
							}
						}
						equation += ") = NoisyOrDist(" + name + ", 0.0,\n" + params + ")\n";
						n.setEquation(equation);
						n.equationToTable(1,false, false);
					
					}
				}
				 
			 }
		  } 
		  catch (NeticaException e) 
		  {
			// TODO Auto-generated catch block
			e.printStackTrace();
		  }
	   	  
	   }
      
  }
  
  
  
  private void removeCyclesBeforeCPT()
  {
	  	try {
	  		   Iterator<Map.Entry<String, associationElement>> assocIterator = myAssociations.getIterator();
		  		 
			   associationElement ae = null;
			   
			   boolean n1_added = false, n2_added = false;
			   Node n1 = null, n2 = null;
				
			   while(assocIterator.hasNext())
			   {	
				  Entry<String, associationElement> entry = assocIterator.next();
	 
				   ae = entry.getValue();
				   snp g_snp = ae.getGsnp();
				   snp p_snp = ae.getPsnp();
				   n1 = (Node) tempNet.getNode(g_snp.getName());
				   n2 = (Node) tempNet.getNode(p_snp.getName());
				   
				   if(n1 != null && n2 != null)
	 			   {
	 					removeCycles(n1,n2);
	 			   }
		 			   
	  		   }
	
				
	  	  } 
		  catch (NeticaException e) 
		  {
			// TODO Auto-generated catch block
			e.printStackTrace();
		  }
     
  }
  
  
  
  
  private void setCPTableforRow(Node n, int[] pStates, float[] cptRow)
  {
  	 float [] vecp = {0.0f, 0.0f}; 
       
  	 String s = "";
		  
	
		  
		  
		  
  	 try {
			vecp = n.getCPTable(pStates, null);
		  // Does the value exist for this parent states in CPT table
		      if (vecp != null)
		      {
		    	  if (vecp[0]== 0.5) // 50-50 chance then we set it to calculated value
		    	  {
		    		  n.setCPTable(pStates,cptRow);
		    		  System.out.println("Setting CPT for row - " + s + " = " + Float.valueOf(cptRow[0]));
		    		  	    		  
		    	  }
		    	  else
		    	  {
		    		  System.out.println("USED ORIGINAL SCORE!" + s + " = " + Float.valueOf(vecp[0]));
		    		  
		    	  }
		    	  
		      }
		  } 
	      catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
		  }
	      
  }
  
  
  private float[] getCPTableforRow(Node n, int[] pStates)
  {
  	float[] cptRow = {0.f, 0.0f}; 
  	try {
			cptRow = n.getCPTable(pStates, null);
		  } 
	      catch (NeticaException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
		  }
	      return cptRow;
  }
  
  private void removeCycles(Node n1, Node n2)
  {
	  NodeList n2ChildrenList = null;
	
	  NodeList n3ChildrenList = null;
	  NodeList n1ChildrenList = null;
	  
	  try {
		  
		  NodeList retVal = new NodeList(tempNet);
	 
		  
	      Node n = null, nn = null;
		  		  
	      if(n1.isRelated("parent", n2))
		  {
			  n2ChildrenList = n2.getChildren();
			  for(int i=0; i< n2ChildrenList.size(); i++)
			  {
				  if(n3ChildrenList != null)
				  {
					  n3ChildrenList.clear();
				  }
				  n =  (Node) n2ChildrenList.getNode(i);
				  n3ChildrenList = n.getChildren();
				  
				  try {
					  	for(int j=0; j< n3ChildrenList.size(); j++)
					  	{
							 nn = (Node) n3ChildrenList.getNode(j);
							 if(nn.getName().compareTo(n1.getName()) == 0)
							 {
								 // we have a cycle
								 if (n1.isRelated ("child", n))
								 {
									 System.out.println("Cycle: " + n1.getName() + "-" + n2.getName() + "-" + n.getName());
									 deleteLink(n.getName(),n1.getName());
									 n.addLink(n1);
									 //n1.reverseLink(n);
								 }
							 }
						  }
				  } catch (NeticaException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						continue;
				  }
					 
			  }
			  
		  }
		  else if(n2.isRelated("parent", n1))
		  {
			  n1ChildrenList = n1.getChildren();
			  for(int i=0; i< n1ChildrenList.size(); i++)
			  {
				  if(n3ChildrenList != null)
				  {
					  n3ChildrenList.clear();
				  }
				  n =  (Node) n1ChildrenList.getNode(i);
				  n3ChildrenList = n.getChildren();
				  try {
						
					  for(int j=0; j< n3ChildrenList.size(); j++)
					  {
						 nn = (Node) n3ChildrenList.getNode(j);
						 if(nn.getName().compareTo(n2.getName()) == 0)
						 {
							 // we have a cycle
							 if (n2.isRelated ("child", n) )
							 {
								 System.out.println("Cycle: " + n1.getName() + "-" + n2.getName() + "-" + n.getName());
								 deleteLink(n.getName(),n2.getName());
								 n.addLink(n2);
								 //n2.reverseLink(n);
							 }
						 }
					  }
				  } catch (NeticaException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						continue;
				  }
			  }
		 
		  }
	      
	      
		  
		  
		  
		  
	  } catch (NeticaException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		
	  }
	 
	  
	  	
  }
  
  

    private void parseAssocFile(String name) {
	// TODO Auto-generated method stub
    	
    	if(name != null)
        {
        
    	  	try {
    	  			BufferedReader input =  new BufferedReader(new FileReader(name));
    	  				
    	  				try {
  
    	  					myAssociations.clear();
  
    	  					String line = null;
    	  					while( (line = input.readLine()) != null)
    	    	  			{
    	  						String[] elements = line.split("\t");
								Float f = new Float(elements[2]);
								snp g_snp = new snp(elements[0]);
								snp p_snp = new snp(elements[1]);
								
								if(elements[7].compareTo("?") == 0)
								{
									g_snp.setRaf(new Float(0.5f));
								}
								else if(elements[7].compareTo("NR") == 0)
								{
									g_snp.setRaf(new Float(0.5f));
								}
								else
								{
									g_snp.setRaf(new Float(elements[7]));
								}
								
								if(elements[8].compareTo("?") == 0)
							    {
									p_snp.setRaf(new Float(0.5f));
								}
								else if(elements[8].compareTo("NR") == 0)
							    {
									p_snp.setRaf(new Float(0.5f));
								}
								else
								{
									p_snp.setRaf(new Float(elements[8]));
								}
								
								if(elements.length >= 10)
								{
									g_snp.setRA(elements[9]);
									p_snp.setRA(elements[10]);
								}
								
								if(elements.length >= 7)
								{
									myAssociations.setAssociation(g_snp,p_snp,f, elements[3], elements[5], elements[4], elements[6]);
								}
								else
								{
									myAssociations.setAssociation(g_snp,p_snp,f, null, null, null, null);
									
								}
    	    	  			}
    	  		    	  					
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							System.out.println(e);
						}
					
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					System.out.println(e);
				}
				
			
        }
	
}
    
    private void drawDAG_traits()
    {
    	try {
  			   Iterator<Map.Entry<String, associationElement>> assocIterator = myAssociations.getIterator();
  			   
  			   Iterator<Map.Entry<String, Float>> g_traitIterator;
  			   Iterator<Map.Entry<String, Float>> p_traitIterator;
			   
  			   boolean t1_added = false, t2_added = false;
			   Node t1 = null, t2 = null;
			   String g_trait, p_trait, trait;
			   
  			   associationElement ae = null;
  			   if(tempNet == null)
  			   {
  				   tempNet = new Net();
  			   }
  			   if(traitList == null)
			   {
				 traitList = new LinkedList<String> ();
			   }
  			 
  			   while(assocIterator.hasNext())
  			   {	
  				   ae = assocIterator.next().getValue();
  				   snp g_snp = ae.getGsnp();
  				   snp p_snp = ae.getPsnp();
  				   
				   g_traitIterator = g_snp.getIterator();
				   p_traitIterator = p_snp.getIterator();
				   
  				   while(g_traitIterator.hasNext())
  				   {
  					   trait = g_traitIterator.next().getKey().replace('-', ' ').replace('.', ' ').replace('\'', ' ').replace('(', ' ')
  					   .replace(')', ' ').replace(',' , ' ').replace('/',' ').replace(' ', '_');
  					   if(trait.length() >= 30)
  					   {
  						   g_trait = trait.substring(0,29);
  					   }
  					   else
  						   g_trait = trait;
  					   
  					   if((tempNet.getNode(g_trait)) == null)
	 	 				{
  						    t1 = new Node(g_trait, "True, False", tempNet);
	 	 					t1_added = true;
	 	 					traitList.add(g_trait);
	 	 					totalTraits++;
	 	 					
	 	 					if(tempNet.getNode(g_snp.getName()) != null)
	 	 					{
	 	 						if(!tempNet.getNode(g_snp.getName()).isRelated("parent", tempNet.getNode(g_trait)))
	 	 			 			{
	 	 							tempNet.getNode(g_trait).addLink(tempNet.getNode(g_snp.getName()));
	 		 					}
	 	 					}
	 	 								 					
	 	 				}
	 	 				else
	 	 				{
	 	 					if(printDebug)
	 	 					{
	 	 						System.out.println("Duplicate trait: " + g_trait);
	 	 					}
	 	 					t1_added = false;
	 	 					if(tempNet.getNode(g_snp.getName()) != null)
	 	 					{
	 	 						if(!tempNet.getNode(g_snp.getName()).isRelated("parent", tempNet.getNode(g_trait)))
	 	 			 			{
	 	 							tempNet.getNode(g_trait).addLink(tempNet.getNode(g_snp.getName()));
	 	 			 			}
	 	 					}
	 	 				}
 	 				
  				   }
	  				
  				   
	  				 while(p_traitIterator.hasNext())
					   {
	  					   trait = p_traitIterator.next().getKey().replace('-', ' ').replace('.', ' ').replace('\'', ' ').replace('(', ' ')
	  					   .replace(')', ' ').replace(',' , ' ').replace('/',' ').replace(' ', '_');
	  					
	  					 if(trait.length() >= 30)
	  					   {
	  						   p_trait = trait.substring(0,29);
	  					   }
	  					   else
	  						   p_trait = trait;
	  					   
						   if((tempNet.getNode(p_trait)) == null)
		 	 				{
								t2 = new Node(p_trait, "True, False", tempNet);
		 	 					t2_added = true;
		 	 					traitList.add(p_trait);
		 	 					totalTraits++;
		 	 					
		 	 					if(tempNet.getNode(p_snp.getName()) != null)
		 	 					{
		 	 						if(!tempNet.getNode(p_snp.getName()).isRelated("parent", tempNet.getNode(p_trait)))
		 	 			 			{
		 	 							tempNet.getNode(p_trait).addLink(tempNet.getNode(p_snp.getName()));
		 		 					}
		 	 					}
		 	 								 					
		 	 				}
		 	 				else
		 	 				{
		 	 					if(printDebug)
		 	 					{
		 	 						System.out.println("Duplicate trait: " + p_trait);
		 	 					}
		 	 					t2_added = false;
		 	 					if(tempNet.getNode(p_snp.getName()) != null)
		 	 					{
		 	 						if(!tempNet.getNode(p_snp.getName()).isRelated("parent", tempNet.getNode(p_trait)))
		 	 			 			{
		 	 							tempNet.getNode(p_trait).addLink(tempNet.getNode(p_snp.getName()));
		 	 			 			}
		 	 					}
		 	 				}
		 				
					   }
  			   }
   	
  		  				
    	} catch (NeticaException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
		System.out.println(e1);
    	}
    	 	
    }
    
    private void deleteLink (String p, String c) throws NeticaException {
    	
    	Node parent = (Node) tempNet.getNode(p);
    	Node child = (Node) tempNet.getNode(c);
		
        NodeList parents = child.getParents();
        int index = parents.indexOf (parent);
        if(index != -1)
        {	
        	child.deleteLink (index);
        }
    }
    
    private void prune()
    {
    	Iterator<partialAssociationElement> peListIterator = triangulations.iterator();
    	System.out.println("Total triangulations:" + triangulations.size());
    	int delLinkCount = 0;
        while(peListIterator.hasNext())
        {
      	  partialAssociationElement pe = peListIterator.next();
      	  ArrayList<String> al = pe.calculatePartialAssociation();
      	  if(printDebug)
      	  {
      		  System.out.println("Traingulations: " + pe.toString());
      		  System.out.println("Remove links: " + al.toString());
      		  System.out.println();
      	  }
      	  // Get the list of links to be ***REMOVED****
      	  Iterator<String> it = al.iterator();
      	  
      	  while(it.hasNext())
      	  {
      		 String link = it.next();
      		 String[] snp = link.split("-");
      	 	 try {
      	 		 delLinkCount++;
				deleteLink(snp[0], snp[1]);
			} catch (NeticaException e) {
				// TODO Auto-generated catch block
				// TODO Auto-generated catch block
				System.out.println("Cannot delete link between" + link);
				e.printStackTrace();
			}
		  }
      	  
        } 
        System.out.println("Total links deleted: " + delLinkCount); 
    }
    
    private void triangulate()
    {
    	 Iterator<Map.Entry<String, associationElement>> assocIterator = myAssociations.getIterator();
	  		 
		   associationElement ae = null;
		   Node n1 = null, n2 = null;
		   if(triangulations == null)
		   {
			   triangulations = new LinkedList<partialAssociationElement>();
		   }
		   while(assocIterator.hasNext())
		   {	
			   ae = assocIterator.next().getValue();
			   snp g_snp = ae.getGsnp();
			   snp p_snp = ae.getPsnp();
			   if(tempNet != null)
			   {
				   try {
					String g =   g_snp.getName();
					String p =  p_snp.getName();
					n1 = (Node) tempNet.getNode(g);
					n2 = (Node) tempNet.getNode(p);
					
					NodeList nl = findCommonChildren(n1, n2);
					if(nl != null)
					{
						for (int i=0; i<nl.size();i++)
						{	
							String c = nl.getNode(i).getName();
							Float gp=0.0f, gc=0.0f, pc=0.0f;
							associationElement aelem = null;
							partialAssociationElement pe = new partialAssociationElement(g,p,c);
							aelem = myAssociations.getAssociation(g+"-"+p);
							if(aelem == null)
							{
								aelem = myAssociations.getAssociation(p+"-"+g);
							}
							if(aelem != null)
							{
								gp = aelem.getRsquared();
							}
							
							aelem = myAssociations.getAssociation(g+"-"+c);
							if(aelem == null)
							{
								aelem = myAssociations.getAssociation(c+"-"+g);
									
							}
							if(aelem != null)
							{
								gc = aelem.getRsquared();
							}
							
							aelem = myAssociations.getAssociation(p+"-"+c);
							if(aelem == null)
							{
								aelem = myAssociations.getAssociation(c+"-"+p);
							}
							if(aelem != null)
							{
								pc = aelem.getRsquared();
							}
							pe.set_Rsquare(gp, gc, pc);
							triangulations.add(pe);
							if(printDebug)
							{
								System.out.println("n1 - n2 - n3: " + g + "-" + p + "-" + c );
							}
						}
					}
				   } 
				   catch (NeticaException e) 
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				
			   }
		   }
    	
    }
    
    
    private void drawDAG()
    {
    	try {
  			   Iterator<Map.Entry<String, associationElement>> assocIterator = myAssociations.getIterator();
  			  		 
  			   associationElement ae = null;
  			   if(tempNet == null)
  			   {
  				   tempNet = new Net();
  			   }
  			   if(snpListByRSquare == null)
  			   {
  				 snpListByRSquare = new LinkedList<snp> ();
  			   }
  			   
  			   boolean n1_added = false, n2_added = false;
			   Node n1 = null, n2 = null;
				
  			   while(assocIterator.hasNext())
  			   {	
  				  Entry<String, associationElement> entry = assocIterator.next();
  				//   System.out.println("Association - " + entry.getKey());
  				   ae = entry.getValue();
  				   snp g_snp = ae.getGsnp();
  				   snp p_snp = ae.getPsnp();
				   
	  				 if((tempNet.getNode(g_snp.getName())) == null)
	 				{
	 					n1 = new Node(g_snp.getName(), "true, false", tempNet);
	 					n1_added = true;
	 					snpListByRSquare.add(g_snp);
	 					if(snpsInNet.get(g_snp.getName()) == null)
	 				 	{
	 						snpsInNet.put(g_snp.getName(), g_snp);
	 				 	}
	 					totalSNPs++;				
	 				}
	 				else
	 				{
	
	 					n1_added = false;
	 				}
	 				if((tempNet.getNode(p_snp.getName())) == null)
	 				{
	 					n2 = new Node(p_snp.getName(), "true, false", tempNet);
	 					n2_added = true;
	 					snpListByRSquare.add(p_snp);
	 					if(snpsInNet.get(p_snp.getName()) == null)
	 				 	{
	 						snpsInNet.put(p_snp.getName(), p_snp);
	 				 	}
	 					totalSNPs++;
	 				}
	 				else
	 				{
	
	 					n2_added = false;
	 				}
	 				if(n1_added && n2_added)
	 				{
	 					removeCycles(n1,n2);
	 					n2.addLink(n1);
	 					
	 				}
	 				else if(n1_added && !n2_added)
	 				{
	 					removeCycles(n1,n2);
	 					n1.addLink(tempNet.getNode(p_snp.getName()));
	 					
	 				}
	 				else if (n2_added && !n1_added)
	 				{
	 					removeCycles(n1,n2);
	 					n2.addLink(tempNet.getNode(g_snp.getName()));
	 				}
	 				else if(!n1_added && !n2_added)
	 				{
	 					if(!tempNet.getNode(g_snp.getName()).isRelated("parent", tempNet.getNode(p_snp.getName())))
	 					{
	
	 							tempNet.getNode(p_snp.getName()).addLink(tempNet.getNode(g_snp.getName()));
	 					}
	 				}
  			   }
   	
  				
  	  			
  				
    	} catch (NeticaException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
		System.out.println(e1);
    	}
    	
    	
    }
   
    /** 
     *  Handy method to absorb nodes.
     *  @param node the node to be removed from its net
     */
    public void absorbNode (Node node) throws NeticaException {
        Net net = node.getNet();
        NodeList nodes = new NodeList (net);
        nodes.add (node);
        net.absorbNodes (nodes);
    }
    
}